package org.jpro.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.jpro.annotation.DataSource;
import org.jpro.common.util.GenericsUtils;
import org.jpro.datasource.DataSourceContextHolder;
import org.jpro.enums.DataSourceType;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

/**
 * <P>功能描述 : 使用AOP切换数据源 </P>
 * <P>File name : DataSourceExchange </P>
 * <P>Author : 王泽浩 </P>
 * <P>E-Mail : 1028625100@qq.com </P>
 * <P>Date : 2017/1/1 下午9:23</P>
 */
@Aspect
@Slf4j
@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceExchange {

    /**
     * 那些前缀的要走写库
     */
    private String[] exchange = { "delete", "remove", "save", "update", "add" };

    @Before("execution(* org.jpro.modules.*.dao.*.*(..)) || execution(* org.jpro.common.jpa.*.*(..))")
    public void before(JoinPoint joinPoint) throws ClassNotFoundException {
        String methodName = joinPoint.getSignature().getName();
        DataSource dataSource = GenericsUtils.getAnnontationByJoinPoint(joinPoint, DataSource.class);
        if (dataSource != null) {
            if (dataSource.compulsoryse()) {
                DataSourceContextHolder.setDataSourceType(dataSource.type());
            } else {
                // 还要判断是不是在调用方法前设置了读写连接
                // 如果调用方法前没有设置读写类型，那么使用注解默认数据源
                DataSourceType dataSourceType = DataSourceContextHolder.getDataSourceType();
                if (dataSourceType == null) {
                    DataSourceContextHolder.setDataSourceType(dataSource.type());
                }
            }
        } else {
            DataSourceType dataSourceType = DataSourceContextHolder.getDataSourceType();
            if (dataSourceType == null) {
                // 这里判断方法名，来设置读写连接
                for (String methodNames : exchange) {
                    if (methodName.startsWith(methodNames)) {
                        DataSourceContextHolder.setDataSourceType(DataSourceType.WRITE);
                        return;
                    }
                }
                DataSourceContextHolder.setDataSourceType(DataSourceType.READ);
            }
        }
    }
}
